﻿using wscf.lightblue;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Text;
using System.Xml;
using System.ServiceModel.Description;
using System.Web.Services.Description;

namespace wscf.lightblue.Test
{
	[TestClass()]
	public class CodeGeneratorTest 
	{
		[TestMethod()]
		public void GenerateCode_Wsdl_Test()
		{
			string generatedFileName = "CodeGeneratorTest.GenerateCodeWsdlTest.cs";
			File.Delete(generatedFileName);
			
			string metadataFiles = "WS_0001_Person v1.wsdl";
			string outputFile = generatedFileName;
			Dictionary<string, string> xmlNamespaceMappings = new Dictionary<string, string>();
			xmlNamespaceMappings.Add("*", "wscf.lightblue.Test.WS_0001_Person");
			List<string> referencedAssemblies = new List<string>()
			{
				"wscf.lightblue.Test.Common.dll"
			};
			string configurationFile = "web.config";
			CodeGenerator.GenerateCode(metadataFiles, outputFile,
				ClrLanguage.cs, xmlNamespaceMappings, 
				referencedAssemblies, false, configurationFile, false);
			Debug.Write(CodeGenerator.ConsoleOutput);

			Assert.IsTrue(File.Exists(generatedFileName));
			string generatedFile = "";
			using (StreamReader sr = new StreamReader(generatedFileName))
			{
				generatedFile = sr.ReadToEnd();
			}
			Assert.IsTrue(generatedFile.Contains("public interface WS_0001_Person_v1Interface"));
			Assert.IsFalse(generatedFile.Contains("ReplyAction=\"*\""));
			Assert.IsTrue(generatedFile.Contains("public partial class WS_0001_Person_v1InterfaceClient"));
			Assert.IsTrue(generatedFile.Contains("public partial class FindPersonRequest"));
			Assert.IsFalse(generatedFile.Contains("public partial class RequestHeader"));
		}

		[TestMethod()]
		public void GenerateCode_Xsd_Test()
		{
			string generatedFileName = "CodeGeneratorTest.GenerateCodeXsdTest.cs";
			File.Delete(generatedFileName);

			string metadataFiles = "WS_0001_Person v1.xsd";
			string outputFile = generatedFileName;
			Dictionary<string, string> xmlNamespaceMappings = new Dictionary<string, string>();
			xmlNamespaceMappings.Add("*", "wscf.lightblue.Test.WS_0001_Person");
			List<string> referencedAssemblies = new List<string>()
			{
				"wscf.lightblue.Test.Common.dll"
			};
			string configurationFile = "web.config";
			CodeGenerator.GenerateCode(metadataFiles, outputFile, ClrLanguage.cs, xmlNamespaceMappings, 
				referencedAssemblies, true, configurationFile, false);

			Assert.IsTrue(File.Exists(generatedFileName));
			string generatedFile = "";
			using (StreamReader sr = new StreamReader(generatedFileName))
			{
				generatedFile = sr.ReadToEnd();
			}
			Assert.IsTrue(generatedFile.Contains("public partial class FindPersonRequest"));
			Assert.IsFalse(generatedFile.Contains("public partial class RequestHeader"));
		}

		[TestMethod()]
		public void GenerateCode_Wildcard_Test()
		{
			string generatedFileName = "CodeGeneratorTest.GenerateCode_Wildcard_Test.cs";
			File.Delete(generatedFileName);

			string metadataFiles = "WS_0001_Person*";
			string outputFile = generatedFileName;
			Dictionary<string, string> xmlNamespaceMappings = new Dictionary<string, string>();
			List<string> referencedAssemblies = new List<string>()
			{
			  "wscf.lightblue.Test.Common.dll"
			};
			string configurationFile = "web.config";
			CodeGenerator.GenerateCode(metadataFiles, outputFile, ClrLanguage.cs, xmlNamespaceMappings, 
				referencedAssemblies, false, configurationFile, false);

			Assert.IsTrue(File.Exists(generatedFileName));
			string generatedFile = "";
			using (StreamReader sr = new StreamReader(generatedFileName))
			{
				generatedFile = sr.ReadToEnd();
			}
			Assert.IsTrue(generatedFile.Contains("public interface WS_0001_Person_v1Interface"));
			Assert.IsFalse(generatedFile.Contains("ReplyAction=\"*\""));
			Assert.IsTrue(generatedFile.Contains("public partial class WS_0001_Person_v1InterfaceClient"));
			Assert.IsTrue(generatedFile.Contains("public partial class FindPersonRequest"));
			Assert.IsFalse(generatedFile.Contains("public partial class RequestHeader"));
		}

		[TestMethod()]
		public void GenerateCode_File_List_Test()
		{
			string generatedFileName = "CodeGeneratorTest.GenerateCode_File_List_Test.cs";
			File.Delete(generatedFileName);

			string metadataFiles = "WS_0001_Person v1.wsdl;WS_0001_Person v1.xsd;Common.MessageHeaders v1.xsd;Common.Types v1.xsd";
			string outputFile = generatedFileName;
			Dictionary<string, string> xmlNamespaceMappings = new Dictionary<string, string>();
			List<string> referencedAssemblies = new List<string>()
			{
			  "wscf.lightblue.Test.Common.dll"
			};
			string configurationFile = "web.config";
			CodeGenerator.GenerateCode(metadataFiles, outputFile, ClrLanguage.cs, xmlNamespaceMappings, 
				referencedAssemblies, false, configurationFile, false);

			Assert.IsTrue(File.Exists(generatedFileName));
			string generatedFile = "";
			using (StreamReader sr = new StreamReader(generatedFileName))
			{
				generatedFile = sr.ReadToEnd();
			}
			Assert.IsTrue(generatedFile.Contains("public interface WS_0001_Person_v1Interface"));
			Assert.IsFalse(generatedFile.Contains("ReplyAction=\"*\""));
			Assert.IsTrue(generatedFile.Contains("public partial class WS_0001_Person_v1InterfaceClient"));
			Assert.IsTrue(generatedFile.Contains("public partial class FindPersonRequest"));
			Assert.IsFalse(generatedFile.Contains("public partial class RequestHeader"));
		}

		[TestMethod()]
		[ExpectedException(typeof(Exception))]
		public void GenerateCodeFailTest()
		{
			string metadataFiles = "NotExisting.wsdl";
			string outputFile = null;
			Dictionary<string, string> xmlNamespaceMappings = null;
			List<string> referencedAssemblies = null;
			string configurationFile = "";
			try
			{
				CodeGenerator.GenerateCode(metadataFiles, outputFile, ClrLanguage.cs, xmlNamespaceMappings, 
					referencedAssemblies, false, configurationFile, false);
			}
			catch (Exception exc)
			{
				Debug.Print(exc.Message);
				throw;
			}
		}

		[TestMethod()]
		public void GenerateWsdl_Test()
		{
			string generatedFileName = "CodeGeneratorTest.GenerateWsdl_Test.wsdl";
			//File.Delete(generatedFileName);

			string outputFile = generatedFileName;
			string ns = CodeGenerator.GetSchemaNamespace("WS_0001_Person v1.xsd");
			List<string> schemas = new List<string>()
			{
				"WS_0001_Person v1.xsd"
				, "Common.MessageHeaders v1.xsd"
				,"Common.Fault v1.xsd"
			};
			CodeGenerator.GenerateWsdl("WS_0001_Person", ns, generatedFileName, schemas, "RequestHeader", "ResponseHeader", "Fault");

			Assert.IsTrue(File.Exists(generatedFileName));
			string generatedFile = "";
			using (StreamReader sr = new StreamReader(generatedFileName))
			{
				generatedFile = sr.ReadToEnd();
			}
			Assert.IsTrue(generatedFile.Contains("soap:operation soapAction=\"http://wscf/WS_0001_Person/v1:findPersonIn\""));
			//Assert.IsTrue(generatedFile.Contains("soap:header message=\"import0:FindPersonInHeader\""));
			Assert.IsFalse(generatedFile.Contains("soap:fault use=\"literal\" name=\"Fault\" namespace=\"\""));
		}

		[TestMethod()]
		public void GetSchemasFromXsdTest()
		{
			string filename = "WS_0001_Person v1.xsd";
			HashSet<string> expected = new HashSet<string>()
			{
				"WS_0001_Person v1.xsd",
				"Common.Types v1.xsd"
			};

			List<string> actual = CodeGenerator.GetSchemasFromXsd(filename);

			Assert.AreEqual(expected.Count, actual.Count);
			for (int i = 0; i < actual.Count; i++)
			{
				Debug.Print("\"{0}\"", actual[i]);
			}
			foreach(string s in actual)
			{
				Assert.IsTrue(expected.Contains(Path.GetFileName(s)));
			}
		}

		[TestMethod()]
		public void GetSchemasFromWsdlTest()
		{
			string filename = "WS_0001_Person v1.wsdl";
			List<string> expected = new List<string>()
			{
				"Common.MessageHeaders v1.xsd",
				"Common.Fault v1.xsd",
				"WS_0001_Person v1.wsdl",
				"WS_0001_Person v1.xsd",
				"Common.Types v1.xsd"
			};

			List<string> actual = CodeGenerator.GetSchemasFromWsdl(filename);

			for (int i = 0; i < actual.Count; i++)
			{
				Debug.Print("\"{0}\"", actual[i]);
			}
			Assert.AreEqual(expected.Count, actual.Count);
			foreach (string s in actual)
			{
				Assert.IsTrue(expected.Contains(Path.GetFileName(s)));
			}
		}

		[TestMethod()]
		public void ExpandSchemas_Wsdl_Test()
		{
			string metadataFiles = "WS_0001_Person v1.wsdl";
			List<string> expected = new List<string>()
			{
				"Common.MessageHeaders v1.xsd",
				"Common.Fault v1.xsd",
				"WS_0001_Person v1.wsdl",
				"WS_0001_Person v1.xsd",
				"Common.Types v1.xsd"
			};
			List<string> actual = CodeGenerator.ExpandSchemas(metadataFiles);

			Assert.AreEqual(expected.Count, actual.Count);
			for (int i = 0; i < actual.Count; i++)
			{
				Debug.Print("\"{0}\"", actual[i]);
			}
			foreach (string s in actual)
			{
				Assert.IsTrue(expected.Contains(Path.GetFileName(s)));
			}
		}

		[TestMethod()]
		public void ExpandSchemas_Xsd_Test()
		{
			string metadataFiles = "WS_0001_Person v1.xsd";
			List<string> expected = new List<string>()
			{
				"WS_0001_Person v1.xsd",
				"Common.Types v1.xsd"
			};
			List<string> actual = CodeGenerator.ExpandSchemas(metadataFiles);

			Assert.AreEqual(expected.Count, actual.Count);
			for (int i = 0; i < actual.Count; i++)
			{
				Debug.Print("\"{0}\"", actual[i]);
			}
			foreach (string s in actual)
			{
				Assert.IsTrue(expected.Contains(Path.GetFileName(s)));
			}
		}

		[TestMethod()]
		public void ExpandSchemas_Multiple_Files_Test()
		{
			string metadataFiles = "WS_0001_Person v1.xsd;Common.Types v1.xsd";
			List<string> expected = new List<string>()
			{
				"WS_0001_Person v1.xsd",
				"Common.Types v1.xsd"
			};
			List<string> actual = CodeGenerator.ExpandSchemas(metadataFiles);

			Assert.AreEqual(expected.Count, actual.Count);
			for (int i = 0; i < actual.Count; i++)
			{
				Debug.Print("\"{0}\"", actual[i]);
				actual[i] = Path.GetFileName(actual[i]);
			}
			foreach (string s in actual)
			{
				Assert.IsTrue(expected.Contains(Path.GetFileName(s)));
			}
		}

		[TestMethod()]
		public void ExpandSchemas_Wildcard_Test()
		{
			string metadataFiles = "WS_0001_Person*";
			List<string> expected = new List<string>()
			{
				"Common.MessageHeaders v1.xsd",
				"Common.Fault v1.xsd",
				"WS_0001_Person v1.wsdl",
				"WS_0001_Person v1.xsd",
				"Common.Types v1.xsd"
			};
			List<string> actual = CodeGenerator.ExpandSchemas(metadataFiles);

			Assert.AreEqual(expected.Count, actual.Count);
			for (int i = 0; i < actual.Count; i++)
			{
				Debug.Print("\"{0}\"", actual[i]);
				actual[i] = Path.GetFileName(actual[i]);
			}
			foreach (string s in actual)
			{
				Assert.IsTrue(expected.Contains(Path.GetFileName(s)));
			}
		}

		[TestMethod()]
		[DeploymentItem("wscf.lightblue.dll")]
		public void RemoveReplyActionTest()
		{
			string wsdlData = "[System.ServiceModel.OperationContractAttribute(Action=\"http://soa.org/Svc/v1:op\"In\", ReplyAction=\"*\")]";
			string expected = "[System.ServiceModel.OperationContractAttribute(Action=\"http://soa.org/Svc/v1:op\"In\")]";
			string actual;
			actual = CodeGenerator_Accessor.RemoveReplyAction(wsdlData);
			Assert.AreEqual(expected, actual);
		}

		[TestMethod()]
		[DeploymentItem("wscf.lightblue.dll")]
		public void RemoveReplyActionTestLineBreak()
		{
			string wsdlData = "[System.ServiceModel.OperationContractAttribute(Action=\"http://soa.org/Svc/v1:op\" +"
						+ '\n' + "\"In\", ReplyAction=\"*\")]";
			string expected = "[System.ServiceModel.OperationContractAttribute(Action=\"http://soa.org/Svc/v1:op\" +"
						+ '\n' + "\"In\")]";
			string actual;
			actual = CodeGenerator_Accessor.RemoveReplyAction(wsdlData);
			Assert.AreEqual(expected, actual);
		}
	}
}
